#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <curses.h>
#include <string.h>
#include "textbuff.h"

list *begin; //The beggining of the file, will only be accessed by one thread if locks are correctly used
char *Final; //Used to free the final line from getline
int invalid;
int nullset;

void init_textbuff(char* file)
{
	FILE *F;

	invalid = 0; //Meaning that the textbuff is valid
	
	if((F = fopen(file,"r")) == NULL)
	{
		perror("Failed to open file from input");
		exit(0);
	}
	
	
	int tmpC;
	int currentLine = 0;
	begin = (list*) malloc(sizeof(list));
	list *tmp;
	tmp = begin;
	for(nullset = 0; nullset < LINEMAX;nullset++)
	{
		tmp->LineC[nullset].data = NULL;
	}
	tmp->line = currentLine;
	tmp->next = NULL;
	
	
	while((tmpC = fgetc(F)) != EOF)//Since the File could '\n' to terminate the line
	{
	
		if((tmpC != '\n') && (tmp->length != LINEMAX))
		{
			tmp->LineC[tmp->length].data = (char*) malloc(sizeof(char));
			*(tmp->LineC[tmp->length].data) = tmpC; //So the value that data points to is now equal to tmpc
			tmp->length++;
			if((tmpC = fgetc(F)) == EOF) //If the file doesn't end with \n
			{
				tmp->length--;
				tmp->next = NULL;
				break;
			}
			if(ungetc(tmpC,F) == EOF)
			{
				perror("Fatal Error occurred");
				exit(0);
			}
		}
	
		else if(tmp->length == LINEMAX) //New Line is needed
		{
			tmp->length--; //To continue representing 
			currentLine++;
			tmp->next = (list*) malloc(sizeof(list));
			tmp = tmp->next;
			for(nullset = 0; nullset < LINEMAX;nullset++)
			{
				tmp->LineC[nullset].data = NULL;
			}
			tmp->length = 0;
			tmp->line = currentLine;
			tmp->next = NULL;
		}
	
	
		//This means that if tmpC = \n and there was a newline created then there would create an entire empty, whether or not this is correct is unknown
		else if(tmpC == '\n') //New line is needed
		{	
			tmp->length--;
			if((tmpC = fgetc(F)) == EOF)
			{
				tmp->next = NULL;
				break;
			}
			if(ungetc(tmpC,F) == EOF)
			{
				perror("Fatal Error occurred");
				exit(0);
			}
			currentLine++;
			tmp->next = (list*) malloc(sizeof(list));
			tmp = tmp->next;
			for(nullset = 0; nullset < LINEMAX;nullset++)
			{
				tmp->LineC[nullset].data = NULL;
			}
			tmp->length = 0;
			tmp->line = currentLine;
			tmp->next = NULL;
		}
		
		
	}
	if(feof(F) != 1) //Assuming 1 is the success
	{
		//Did not hit end of file
		perror("End of file not reached, critical error");
		exit(0); //Need to exit the program and try again, something interruptted reading
	}
	
	
	
	return; //Meaning Success
}

int appendLine(char* line)
{
	

	return 1;
}

int getLine(int index, char** returnLine)
{
	list *tmp;
	tmp = begin;
	
	while(tmp != NULL)//To iterate until the line containing the specified index is found
	{
		if(tmp->line == index)
		{
			break;
		}
		tmp = tmp->next;
	}
	
	if(tmp == NULL)
	{
		return 0;
	}
	char *tmpData = (char*) malloc(((tmp->length)+1)*sizeof(char));
	//Don't Forget to free last remaining line in editor when closing
	
	int i;
	for(i = 0; i <= tmp->length;i++)
	{
		if(tmp->LineC[i].data == NULL)
		{
			break;
		}	
		tmpData[i] = *(tmp->LineC[i].data);
	}

	if(*returnLine != NULL)
	{
		free(*returnLine); //So that memory is not leaked
	}
	
	
	
	*returnLine = tmpData;
	
	Final = tmpData; //Used since the last line won't be freed, or last call to this function
	
	return 1;
}

int insert(int row, int col, char text)
{
	list *tmp;
	tmp = begin;
	char tmpData;	//Used later to hold temporary data/addresses
	char tmpData2;
	int tmpInt; //Used later as well
	int newLine;
	
	while(tmp != NULL)//To iterate until the line containing the specified row is found
	{
		if(tmp->line == row)
		{
			break;
		}
		tmp = tmp->next;
	}
	
	if(tmp == NULL)
	{
		perror("Did not find specified row");
		return 0; //Represents error
	}
	
	if((tmp->LineC[col].data == NULL) && col != 0)
	{
		return 0; //Will not input in middle of file if has been declared NULL
	}
	
	else if((tmp->LineC[col].data == NULL) && col == 0) //If attempting to add a newline persay
	{
		tmp->LineC[col].data = (char*) malloc(sizeof(char));
		*(tmp->LineC[col].data) = text;
		tmp->length = 0;
		return 1;
	}
	
	else if((tmp->length + 1) != LINEMAX)
	{
		tmpInt = col;
		if(col > (tmp->length + 1)) //Not at the end of the line, won't insert
		{
			return 0;
		}
		else if(col == (tmp->length + 1)) //Simply make new char
		{
			if(tmp->LineC[col].data != NULL)
				return 0;
				
			tmp->LineC[col].data = (char*) malloc(sizeof(char));
			*(tmp->LineC[col].data) = text;
			tmp->length++;
			return 1;
		}
		else if(col < (tmp->length + 1))
		{
			tmpData = *(tmp->LineC[tmpInt].data);
			*(tmp->LineC[tmpInt].data) = text;
			tmpInt++;
			while(tmpInt <= tmp->length)
			{
					tmpData2 = *(tmp->LineC[tmpInt].data);
					*(tmp->LineC[tmpInt].data) = tmpData;
					tmpData = tmpData2;
					tmpInt++;
			}
				
			tmp->LineC[tmpInt].data = (char*) malloc(sizeof(char));
			*(tmp->LineC[tmpInt].data) = tmpData;
			tmp->length++;
			
			return 1;
			
			
			
		}
		
		else
			return 0;
	}
		
	else if((tmp->length + 1) == LINEMAX)	
	{
		tmpInt = col;
		tmpData = *(tmp->LineC[tmpInt].data);
		*(tmp->LineC[tmpInt].data) = text;
		tmpInt++;
		while((tmp->length + 1) == LINEMAX)
		{
			while(tmpInt <= tmp->length)
			{
				tmpData2 = *(tmp->LineC[tmpInt].data);
				*(tmp->LineC[tmpInt].data) = tmpData;
				tmpData = tmpData2;
				tmpInt++;
			}
			tmpInt = 0;
			if(tmp->next == NULL) //New line is needed and next char gets placed here
			{
				tmp->next = (list*) malloc(sizeof(list));
				newLine = (tmp->line + 1);
				tmp = tmp->next;
				for(nullset = 0; nullset < LINEMAX;nullset++)
				{
					tmp->LineC[nullset].data = NULL;
				}
				tmp->length = 0;
				tmp->line = newLine;
				tmp->next = NULL;
				tmp->LineC[tmpInt].data = (char*) malloc(sizeof(char));
				*(tmp->LineC[tmpInt].data) = tmpData;
				return 1;
				
			}
			
			tmp = tmp->next;
		}
		
		if((tmp->length + 1) != LINEMAX)//Room in this line
		{
			while(tmpInt <= tmp->length)
			{
				tmpData2 = *(tmp->LineC[tmpInt].data);
				*(tmp->LineC[tmpInt].data) = tmpData;
				tmpData = tmpData2;
				tmpInt++;
			}
			
			if(tmp->LineC[tmpInt].data == NULL)
			{
				tmp->LineC[tmpInt].data = (char*) malloc(sizeof(char));
			}
			*(tmp->LineC[tmpInt].data) = tmpData;
			tmp->length++;
			
			return 1;
		}
		
		else
			return 0;
	}
		
	
	else
		return 0;
	
	
	return 1;
}

int getLineLength()
{
	list *tmp;
	tmp = begin;
	int returnValue;
	
	if(invalid == 1)
		return -1; //To represent that the buffer is invalid
	
	returnValue = tmp->line;
	while(tmp->next != NULL)
	{
		tmp = tmp->next;
	}
	
	returnValue = tmp->line;
	
	return returnValue;
}

int deleteLine(int index)
{
	return 1;
}

int deleteCharacter(int row, int col)
{
	list *tmp;
	tmp = begin;
	int tmpInt;	//Used later as well
	int newLine;
	
	while(tmp != NULL)//To iterate until the line containing the specified row is found
	{
		if(tmp->line == row)
		{
			break;
		}
		tmp = tmp->next;
	}
	
	if(tmp == NULL)
	{
		return 0; //Represents error
	}

	if(tmp->LineC[col].data == NULL)
	{
		return 1;
	}
	
	else if(((tmp->length + 1) == 1) && (*(tmp->LineC[tmp->length].data) != '\n'))//This is only char in line
	{
		free((tmp->LineC[tmp->length].data));
		tmp->LineC[tmp->length].data = NULL;
	}
	
	else if((tmp->length + 1) != 1)
	{
		tmpInt = col;
		//Data is not being placed into a temp as it is now being deleted, however, its address will be used
		while(tmpInt < tmp->length) //Shifts other nodes from right to left
		{
				*(tmp->LineC[tmpInt].data) = *(tmp->LineC[(tmpInt + 1)].data);
				tmpInt++;
		}
		if(tmp->LineC[tmp->length].data != NULL)
		{
			free((tmp->LineC[tmp->length].data));
		}	
		tmp->LineC[tmp->length].data = NULL;
		tmp->length--;
	}
	

	return 1;
}

void deleteBuffer()
{
	list *tmp;
	list *tmp2;
	tmp = begin;
	int tmpInt;
	
	printf("GOT HERE\n",NULL);
	tmpInt = 0;
	while(tmp != NULL)
	{
		tmp2 = tmp;
		while(tmpInt < (tmp->length + 1))
		{
			if(tmp->LineC[tmpInt].data != NULL)
			{
				free(tmp->LineC[tmpInt].data);
			}	
			tmpInt++;
		}
		
		tmpInt = 0;
		tmp = tmp->next;
		free(tmp2);
	}
	
	
	invalid = 1; //The buffer is set to being invalid
	free(Final);
	return;
}
